#include "usart.h"	

#include "platform.h"

/*FreeRtos includes*/
#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "cyclequeue.h"

#define USART1_SEND_USE_QUEUE 1  //是否使用队列

/* 加入以下代码,支持printf函数,而不需要选择use MicroLIB	 */ 
#pragma import(__use_no_semihosting_swi)
#pragma import(_main_redirection)
 
const char __stdin_name[150];
const char __stdout_name[150];
const char __stderr_name[150];
typedef int FILEHANDLE;
 
void _sys_exit(int status){
    while(1);
}
FILEHANDLE _sys_open(const char *name, int openmode){
    return 0;
}
 
int _sys_close(FILEHANDLE fh){
    return 0;
}
 
int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode){
    return 0;
}
 
int _sys_read(FILEHANDLE fh, unsigned char*buf, unsigned len, int mode){
    return 0;
}
 
int _sys_istty(FILEHANDLE fh){
    return 0;
}
 
int _sys_seek(FILEHANDLE fh, long pos){
    return 0;
}
 
int _sys_ensure(FILEHANDLE fh){
    return 0;
}
 
long _sys_flen(FILEHANDLE fh){
    return 0;
}
 
int _sys_tmpnam(char *name, int fileno, unsigned maxlength){
    return 0;
}
 
void _ttywrch(int ch){
}

int remove(const char *filename){
    return 0;
}
 
char *_sys_command_string(char *cmd, int len){
    return 0;
}


//重定义fputc函数 
void usart1_send_char(char_t ch);
int fputc(int ch, FILE *f){ 
#if USART1_SEND_USE_QUEUE
    usart1_send_char(ch);
#else
    USART_SendData(USART1, (uint16_t) ch);
    while (!(USART1->SR & USART_FLAG_TXE)){ //循环发送，直到发送完毕   
        //os_msleep(1); //不能加系统延迟，会死机
    }        
#endif
    return ch;
}

/********************************************************************/

static xQueueHandle uart1_recv_queue = NULL;
static xQueueHandle uart5_recv_queue = NULL;

#if USART1_SEND_USE_QUEUE
#define USART_SEND_QUEUE_BUF_MAX (1024U)

static struct CycleQueue *usart1_send_queue = NULL;

void usart1_send_char(char_t ch){
    cycle_queue_push(usart1_send_queue, ch);
    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

}
#endif

/*
  调试口 TX = PA9   RX = PA10
*/
void usart1_init(uint32_t baud)
{
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
 
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
	
	//USART1端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9，PA10

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = baud;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
    USART_Init(USART1, &USART_InitStructure); //初始化串口1
	
    uart1_recv_queue = xQueueCreate(64, sizeof(uint8_t));
#if USART1_SEND_USE_QUEUE    
    usart1_send_queue = cycle_queue_init(USART_SEND_QUEUE_BUF_MAX);
#endif
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
    
    USART_Cmd(USART1, ENABLE);  //使能串口1 
  
    /* CPU的小缺陷：串口配置好，如果直接Send，则第1个字节发送不出去
		如下语句解决第1个字节无法正确发送出去的问题 */
	USART_ClearFlag(USART6, USART_FLAG_TC);     /* 清发送完成标志，Transmission Complete flag */  
}


void usart1_send(const uint8_t *buf, uint32_t len){
    int32_t i;
    for (i = 0; i < len; i++){
        USART_SendData(USART1, buf[i]);
        while (!(USART1->SR & USART_FLAG_TXE)){os_msleep(1);}; //循环发送，直到发送完毕     
    }
}

int32_t usart1_receive(uint8_t *chr){
  BaseType_t xResult = xQueueReceive(uart1_recv_queue, chr, portMAX_DELAY);
  if (xResult != pdPASS){
    return 0;
  }
  return 1;
}

void USART1_IRQHandler(void)                	
{	
	uint8_t res;
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
  
	if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)  //接收到数据
	{
		res = USART_ReceiveData(USART1) & 0x00FF;	//读取接收到的数据
		printf("%c",res);
        xQueueSendFromISR(uart1_recv_queue, &res, &xHigherPriorityTaskWoken);
        USART_ClearITPendingBit(USART1,USART_IT_RXNE); 
	}
    #if USART1_SEND_USE_QUEUE
    /*发送中断*/
    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {  
        uint8_t ch;
        if (cycle_queue_pop(usart1_send_queue, &ch)){
            USART_SendData(USART1, ch);
        }
        
        if (cycle_queue_length(usart1_send_queue) == 0){          
            USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //关闭发送中断
        }
    } 
    #endif
} 

/* 
    串口2 TX = PD5   RX = PD6 
    为电表口，485控制
*/

#define RS485_TX_EN()   GPIO_SetBits(GPIOD,GPIO_Pin_7)
#define RS485_RX_EN()   GPIO_ResetBits(GPIOD,GPIO_Pin_7)

#define USART2_TX_DMA_STEAM DMA1_Stream6
#define USART2_RX_DMA_STEAM DMA1_Stream5
#define USART2_TXRX_DMA_MAX 64

struct t_cli_usart2_rx
{
	uint8_t buffer[USART2_TXRX_DMA_MAX];
	uint32_t len;
	uint32_t posread ;
};
struct t_cli_usart2_rx _cli_usart2_rx;
uint8_t _cli_usart2_tx[USART2_TXRX_DMA_MAX];

void usart2_dma_tx_init(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);   
	
   DMA_DeInit(USART2_TX_DMA_STEAM);  
	 while (DMA_GetCmdStatus(USART2_TX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure.DMA_Channel = DMA_Channel_4; 
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);  
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(_cli_usart2_tx); 
   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;  
   DMA_InitStructure.DMA_BufferSize = USART2_TXRX_DMA_MAX;  
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;   
	 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//单次传输 
	 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设单次突发
		 
   DMA_Init(USART2_TX_DMA_STEAM,&DMA_InitStructure);  
		 
	 DMA_ClearFlag(USART2_TX_DMA_STEAM,DMA_IT_TCIF6);
		 
	 DMA_Cmd(USART2_TX_DMA_STEAM, ENABLE);
   USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);  
}
void usart2_dma_rx_init(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);   
 
  DMA_DeInit(USART2_RX_DMA_STEAM);  
	
	while (DMA_GetCmdStatus(USART2_RX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure.DMA_Channel = DMA_Channel_4; 
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);  
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(_cli_usart2_rx.buffer); 
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;  
   DMA_InitStructure.DMA_BufferSize = USART2_TXRX_DMA_MAX;  
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;   
   DMA_Init(USART2_RX_DMA_STEAM,&DMA_InitStructure);  
		 
	 DMA_Cmd(USART2_RX_DMA_STEAM,ENABLE); 
	 USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);  
}
void usart2_init(uint32_t baud){
   GPIO_InitTypeDef GPIO_InitStructure;
	 USART_InitTypeDef USART_InitStructure;
    
    /* 打开 GPIO 时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    /* 打开 UART 时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    /* 将 PD5 映射为 USART2_TX */
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);

    /* 将 PD6 映射为 USART2_RX */
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);
    
    /* 485控制脚 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	/* 输出类型为推挽 */
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	/* 内部上拉电阻使能 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;	/* 输出模式 */

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    

    /* 配置 USART Tx 为复用功能 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	/* 输出类型为推挽 */
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	/* 内部上拉电阻使能 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;	/* 复用模式 */

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* 配置 USART Rx 为复用功能 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* 配置串口硬件参数 */
	  USART_InitStructure.USART_BaudRate = baud;	/* 波特率 */
	  USART_InitStructure.USART_WordLength = USART_WordLength_9b; //含奇偶校验是需要9b
	  USART_InitStructure.USART_StopBits = USART_StopBits_1;
	  USART_InitStructure.USART_Parity = USART_Parity_Even ;  //电表都是偶校验
	  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	  USART_Init(USART2, &USART_InitStructure);

    USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);/*打开空闲中断*/
		
	  USART_Cmd(USART2, ENABLE);		
		
		memset((uint8_t *)&_cli_usart2_rx,0,sizeof(_cli_usart2_rx));
		memset((uint8_t *)_cli_usart2_tx,0,sizeof(_cli_usart2_tx));
		usart2_dma_tx_init();
	  usart2_dma_rx_init();
	

    uint32_t temp = 0;  //清除空闲中断
  	temp = USART2->SR;  
    temp = USART2->DR; 
	
    RS485_TX_EN();
}

void usart2_send(const uint8_t *buf, uint32_t len){
	RS485_TX_EN();
	os_msleep(5);//不能小于10ms  反正485芯片使能管脚还没切换 就已经发送数据 会导致数据发不出去;
	
	DMA_Cmd(USART2_TX_DMA_STEAM, DISABLE);
	while (DMA_GetCmdStatus(USART2_TX_DMA_STEAM) != DISABLE){}
	
  memcpy(_cli_usart2_tx,buf,len);		
	DMA_SetCurrDataCounter(USART2_TX_DMA_STEAM, len);
  
	DMA_Cmd(USART2_TX_DMA_STEAM, ENABLE);
   while(1){
	  if((DMA_GetFlagStatus(USART2_TX_DMA_STEAM,DMA_IT_TCIF6)!=RESET)){	
	  DMA_ClearFlag(USART2_TX_DMA_STEAM,DMA_IT_TCIF6);
		break;
		}
	}
  os_msleep(10);
  RS485_RX_EN();
}

void USART2_IRQHandler(void)                	
{	
	if(USART_GetITStatus(USART2,USART_IT_IDLE) != RESET){  //接收到数据
	  
  	uint32_t temp = 0;  
	  temp = USART2->SR;  
    temp = USART2->DR; //清USART_IT_IDLE标志 
 		
		DMA_Cmd(USART2_RX_DMA_STEAM,DISABLE);
				
		while (DMA_GetCmdStatus(USART2_RX_DMA_STEAM) != DISABLE){}	//等待传输结束		
		
	  _cli_usart2_rx.len = USART2_TXRX_DMA_MAX - DMA_GetCurrDataCounter(USART2_RX_DMA_STEAM);
		_cli_usart2_rx.posread  = 0;
			
		DMA_SetCurrDataCounter(USART2_RX_DMA_STEAM,USART2_TXRX_DMA_MAX);
	  DMA_ClearFlag(USART2_RX_DMA_STEAM,DMA_FLAG_TCIF5);
					
	  DMA_Cmd(USART2_RX_DMA_STEAM,ENABLE);
		
	}	
	
} 

int32_t usart2_receive(uint8_t *chr){

	if(	_cli_usart2_rx.posread == _cli_usart2_rx.len)
	{
		return 0;
	}
	*chr = _cli_usart2_rx.buffer[_cli_usart2_rx.posread];
	_cli_usart2_rx.posread ++;
	return 1;
}

/*
    读卡器 串口3 TX = PD7   RX = PD8
*/

#define USART3_RX_DMA_STEAM DMA1_Stream1
#define USART3_TX_DMA_STEAM DMA1_Stream3
#define USART3_DMA_RX_BUF 1500
#define USART3_DMA_TX_BUF 1024
#define RX_DMA_MAX 3

struct t_usart3_seg{
	uint8_t pushstate;
	uint32_t head;
	uint32_t len;
	uint8_t usart3_rx_dma[USART3_DMA_RX_BUF];
};
struct t_cli_usart3{
	
	uint32_t pos_pop;
	uint32_t pos_push;
	struct t_usart3_seg list[RX_DMA_MAX];
};
DMA_InitTypeDef DMA_InitStructure_rx;
struct t_cli_usart3 _cli_usart3;
uint8_t _cli_usart3_tx[USART3_DMA_TX_BUF];

void usart3_dma_tx_init()
{
	 DMA_InitTypeDef DMA_InitStructure_tx;
	
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);   
	
   DMA_DeInit(USART3_TX_DMA_STEAM);  
	 while (DMA_GetCmdStatus(USART3_TX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure_tx.DMA_Channel = DMA_Channel_4; 
   DMA_InitStructure_tx.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);  
   DMA_InitStructure_tx.DMA_Memory0BaseAddr = (uint32_t)(_cli_usart3_tx); 
   DMA_InitStructure_tx.DMA_DIR = DMA_DIR_MemoryToPeripheral;  
   DMA_InitStructure_tx.DMA_BufferSize = USART3_DMA_TX_BUF;  
   DMA_InitStructure_tx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure_tx.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure_tx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure_tx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure_tx.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure_tx.DMA_Priority = DMA_Priority_VeryHigh;   
	 DMA_InitStructure_tx.DMA_MemoryBurst = DMA_MemoryBurst_Single;//单次传输 
	 DMA_InitStructure_tx.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设单次突发
		 
   DMA_Init(USART3_TX_DMA_STEAM,&DMA_InitStructure_tx);  
		 
	 DMA_ClearFlag(USART3_TX_DMA_STEAM,DMA_IT_TCIF3);
		 
	 DMA_Cmd(USART3_TX_DMA_STEAM, ENABLE);
   USART_DMACmd(USART3,USART_DMAReq_Tx,ENABLE);  
}
void usart3_dma_rx_init()
{	
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);   
 
   DMA_DeInit(USART3_RX_DMA_STEAM);  
	
	 while (DMA_GetCmdStatus(USART3_RX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure_rx.DMA_Channel = DMA_Channel_4; 
   DMA_InitStructure_rx.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);  
   DMA_InitStructure_rx.DMA_Memory0BaseAddr = (uint32_t)((_cli_usart3.list+_cli_usart3.pos_push)->usart3_rx_dma); 
   DMA_InitStructure_rx.DMA_DIR = DMA_DIR_PeripheralToMemory;  
   DMA_InitStructure_rx.DMA_BufferSize = USART3_DMA_RX_BUF;  
   DMA_InitStructure_rx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure_rx.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure_rx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure_rx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure_rx.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure_rx.DMA_Priority = DMA_Priority_VeryHigh;   
   DMA_Init(USART3_RX_DMA_STEAM,&DMA_InitStructure_rx);  
		
	 DMA_ITConfig(USART3_RX_DMA_STEAM,DMA_IT_TC,ENABLE);	
		 
	 DMA_ClearFlag(USART3_RX_DMA_STEAM,DMA_FLAG_TCIF1);
		 
	 DMA_Cmd(USART3_RX_DMA_STEAM,ENABLE); 
	 USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);  
}

void DMA1_Stream1_IRQHandler()
{	
	if(DMA_GetFlagStatus(USART3_RX_DMA_STEAM,DMA_FLAG_TCIF1) != RESET){
		
	  DMA_Cmd(USART3_RX_DMA_STEAM,DISABLE);
		while (DMA_GetCmdStatus(USART3_RX_DMA_STEAM) != DISABLE){}	//等待传输结束		
	  uint32_t	buff_length = USART3_DMA_RX_BUF - DMA_GetCurrDataCounter(USART3_RX_DMA_STEAM);
		DMA_SetCurrDataCounter(USART3_RX_DMA_STEAM,USART3_DMA_RX_BUF);
	  DMA_ClearFlag(USART3_RX_DMA_STEAM,DMA_FLAG_TCIF1);
			
	  DMA_Cmd(USART3_RX_DMA_STEAM,ENABLE);
			
	  struct t_usart3_seg *plist = _cli_usart3.list+ _cli_usart3.pos_push;
		plist->len = buff_length;
	  plist->head = 0;
		plist->pushstate = 1;
		_cli_usart3.pos_push = (_cli_usart3.pos_push+1)%RX_DMA_MAX;
			
  	usart3_dma_rx_init();
	} 
}

void usart3_init(uint32_t baud){
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
    
	/* 打开 GPIO 时钟 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

	/* 打开 UART 时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

	/* 将 PB10 映射为 USART3_TX */
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);

	/* 将 PB11 映射为 USART3_RX */
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);

	/* 配置 USART Tx 为复用功能 */
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	/* 输出类型为推挽 */
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	/* 内部上拉电阻使能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;	/* 复用模式 */

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	/* 配置 USART Rx 为复用功能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	/* 第2步： 配置串口硬件参数 */
	USART_InitStructure.USART_BaudRate = baud;	/* 波特率 */
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART3, &USART_InitStructure);
	
  USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);	//打开空闲中断
		
	USART_Cmd(USART3, ENABLE);		/* 使能串口 */
	
	memset((uint8_t *)&_cli_usart3,0,sizeof(_cli_usart3));//注意:要先配置好串口功能 再去配置串口dma 不然不成功
	memset(_cli_usart3_tx,0,sizeof(_cli_usart3_tx));
	
  usart3_dma_tx_init();
  usart3_dma_rx_init();
	
  uint32_t temp = 0;  //清除空闲中断
	temp = USART3->SR;  
  temp = USART3->DR; 
}

void usart3_send(const uint8_t *buf, uint32_t len){
	while(1){
	  if((DMA_GetFlagStatus(USART3_TX_DMA_STEAM,DMA_IT_TCIF3)!=RESET)){	
	  DMA_ClearFlag(USART3_TX_DMA_STEAM,DMA_IT_TCIF3);
		break;
		}
	}
	DMA_Cmd(USART3_TX_DMA_STEAM, DISABLE);
	while (DMA_GetCmdStatus(USART3_TX_DMA_STEAM) != DISABLE){}
	
  memcpy(_cli_usart3_tx,buf,len);		
	DMA_SetCurrDataCounter(USART3_TX_DMA_STEAM, len);
  
	DMA_Cmd(USART3_TX_DMA_STEAM, ENABLE);	

}
int32_t usart3_receive_wait(uint8_t *chr, int32_t ms){
  while(1){
	  struct t_usart3_seg  *plist = _cli_usart3.list + _cli_usart3.pos_pop;
	  if (plist->pushstate == 0){
		   return 0;
	  }
	  if ( plist->head  >= plist->len){//表示读完了
		   plist->pushstate = 0;
		   _cli_usart3.pos_pop = (_cli_usart3.pos_pop +1)%RX_DMA_MAX;	
		   continue;
	  }else{
		   break;
	  }
  }
	struct t_usart3_seg  *plist = _cli_usart3.list + _cli_usart3.pos_pop;
	*chr =  plist->usart3_rx_dma[ plist->head ];
	plist->head ++;

	return 1;
}

int32_t usart3_receive(uint8_t *chr){
   return usart3_receive_wait(chr,1);
}

void USART3_IRQHandler(void) {
	
	if(USART_GetITStatus(USART3,USART_IT_IDLE) != RESET){//接收到数据
  	uint32_t temp = 0;  
	  temp = USART3->SR;  
    temp = USART3->DR; //清USART_IT_IDLE标志 
 		
		DMA_Cmd(USART3_RX_DMA_STEAM,DISABLE);
				
		while (DMA_GetCmdStatus(USART3_RX_DMA_STEAM) != DISABLE){}	//等待传输结束		
		
	  uint32_t	buff_length = USART3_DMA_RX_BUF - DMA_GetCurrDataCounter(USART3_RX_DMA_STEAM);
		DMA_SetCurrDataCounter(USART3_RX_DMA_STEAM,USART3_DMA_RX_BUF);
	  DMA_ClearFlag(USART3_RX_DMA_STEAM,DMA_FLAG_TCIF1);
					
	  DMA_Cmd(USART3_RX_DMA_STEAM,ENABLE);			
		
		struct t_usart3_seg *plist = _cli_usart3.list+ _cli_usart3.pos_push;
		plist->len = buff_length;
	  plist->head = 0;
		plist->pushstate = 1;
		_cli_usart3.pos_push = (_cli_usart3.pos_push+1)%RX_DMA_MAX;
			
  	usart3_dma_rx_init();
	}	
}

/*
    读卡器 串口4 TX = PC10   RX = PC11
*/
#define UART4_TX_DMA_STEAM DMA1_Stream4
#define UART4_RX_DMA_STEAM DMA1_Stream2
#define UART4_TXRX_DMA_MAX 64
#define UART4_RX_MAX 5

struct t_uart4_seg{
	uint8_t pushstate;
	uint32_t head;
	uint32_t len;
	uint8_t uart4_rx_dma[UART4_TXRX_DMA_MAX];
};
struct t_cli_uart4{
	uint32_t pos_pop;
	uint32_t pos_push;
	struct t_uart4_seg list[UART4_RX_MAX];
};

uint8_t _cli_uart4_tx[UART4_TXRX_DMA_MAX];
struct t_cli_uart4 _cli_uart4_rx;

DMA_InitTypeDef DMA_InitStructure_uart4_rx;

void usart4_tx_init(void)
{
	 DMA_InitTypeDef DMA_InitStructure;
	
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);   
	
   DMA_DeInit(UART4_TX_DMA_STEAM);  
	 while (DMA_GetCmdStatus(UART4_TX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure.DMA_Channel = DMA_Channel_4; 
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&UART4->DR);  
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(_cli_uart4_tx); 
   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;  
   DMA_InitStructure.DMA_BufferSize = UART4_TXRX_DMA_MAX;  
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;   
	 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//单次传输 
	 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设单次突发
		 
   DMA_Init(UART4_TX_DMA_STEAM,&DMA_InitStructure);  
		 
	 DMA_ClearFlag(UART4_TX_DMA_STEAM,DMA_IT_TCIF4);
		 
	 DMA_Cmd(UART4_TX_DMA_STEAM, ENABLE);
   USART_DMACmd(UART4,USART_DMAReq_Tx,ENABLE);  
}
void usart4_rx_init(void)
{
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);   
 
   DMA_DeInit(UART4_RX_DMA_STEAM);  
	
	 while (DMA_GetCmdStatus(UART4_RX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure_uart4_rx.DMA_Channel = DMA_Channel_4; 
   DMA_InitStructure_uart4_rx.DMA_PeripheralBaseAddr = (uint32_t)(&UART4->DR);  
   DMA_InitStructure_uart4_rx.DMA_Memory0BaseAddr = (uint32_t)((uint32_t)((_cli_uart4_rx.list+_cli_uart4_rx.pos_push)->uart4_rx_dma)); 
   DMA_InitStructure_uart4_rx.DMA_DIR = DMA_DIR_PeripheralToMemory;  
   DMA_InitStructure_uart4_rx.DMA_BufferSize = UART4_TXRX_DMA_MAX;  
   DMA_InitStructure_uart4_rx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure_uart4_rx.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure_uart4_rx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure_uart4_rx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure_uart4_rx.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure_uart4_rx.DMA_Priority = DMA_Priority_VeryHigh;   
   DMA_Init(UART4_RX_DMA_STEAM,&DMA_InitStructure_uart4_rx);  
		
	 DMA_ClearFlag(UART4_RX_DMA_STEAM,DMA_FLAG_TCIF2);
		 
	 DMA_Cmd(UART4_RX_DMA_STEAM,ENABLE); 
	 USART_DMACmd(UART4,USART_DMAReq_Rx,ENABLE);  
		 
}
void usart4_init(uint32_t baud){
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
    
	/* 打开 GPIO 时钟 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

	/* 打开 UART 时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);

	/* 将 PC10 映射为 UART4_TX */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_UART4);

	/* 将 PC11 映射为 UART4_RX */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_UART4);

	/* 配置 USART Tx 为复用功能 */
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	/* 输出类型为推挽 */
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	/* 内部上拉电阻使能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;	/* 复用模式 */

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	/* 配置 USART Rx 为复用功能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	/* 第2步： 配置串口硬件参数 */
	USART_InitStructure.USART_BaudRate = baud;	/* 波特率 */
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(UART4, &USART_InitStructure);


	USART_ITConfig(UART4, USART_IT_IDLE, ENABLE);	
	USART_Cmd(UART4, ENABLE);		

  memset(_cli_uart4_tx,0,sizeof(_cli_uart4_tx));
	memset((uint8_t *)&_cli_uart4_rx,0,sizeof(_cli_uart4_rx));
  usart4_tx_init();
	usart4_rx_init();
	
  uint32_t temp = 0;  
	temp = UART4->SR;  
  temp = UART4->DR; 
 		
}
void usart4_send_chr(uint8_t val){
	while(1){
	  if((DMA_GetFlagStatus(UART4_TX_DMA_STEAM,DMA_IT_TCIF4)!=RESET)){	
	  DMA_ClearFlag(UART4_TX_DMA_STEAM,DMA_IT_TCIF4);
		break;
		}
	}
	DMA_Cmd(UART4_TX_DMA_STEAM, DISABLE);
	while (DMA_GetCmdStatus(UART4_TX_DMA_STEAM) != DISABLE){}
	
  _cli_uart4_tx[0] = val;
	DMA_SetCurrDataCounter(UART4_TX_DMA_STEAM,1);
  
	DMA_Cmd(UART4_TX_DMA_STEAM, ENABLE);	
}

void usart4_send(const uint8_t *buf, uint32_t len){
  while(1){
	  if((DMA_GetFlagStatus(UART4_TX_DMA_STEAM,DMA_IT_TCIF4)!=RESET)){	
	  DMA_ClearFlag(UART4_TX_DMA_STEAM,DMA_IT_TCIF4);
		break;
		}
	}
	DMA_Cmd(UART4_TX_DMA_STEAM, DISABLE);
	while (DMA_GetCmdStatus(UART4_TX_DMA_STEAM) != DISABLE){}
	
  memcpy(_cli_uart4_tx,buf,len);
	DMA_SetCurrDataCounter(UART4_TX_DMA_STEAM,len);
  
	DMA_Cmd(UART4_TX_DMA_STEAM, ENABLE);	
}

int32_t usart4_receive(uint8_t *chr){
  while(1){
	   struct t_uart4_seg *plist = _cli_uart4_rx.list + _cli_uart4_rx.pos_pop;
	   if (plist->pushstate == 0){
		    return 0;
	   }
	   if ( plist->head  >= plist->len){//表示读完了
		    plist->pushstate = 0;
		    _cli_uart4_rx.pos_pop = (_cli_uart4_rx.pos_pop +1)%UART4_RX_MAX;	
		    continue;
	   }else{
		    break;
	   }
  }
	struct t_uart4_seg *plist = _cli_uart4_rx.list + _cli_uart4_rx.pos_pop;
	*chr = plist->uart4_rx_dma[plist->head ];
	plist->head ++;

	return 1;
}

void UART4_IRQHandler(void) {
	if(USART_GetITStatus(UART4,USART_IT_IDLE) != RESET){  //接收到数据
	  
  	uint32_t temp = 0;  
	  temp = UART4->SR;  
    temp = UART4->DR; //清USART_IT_IDLE标志 
 		
		DMA_Cmd(UART4_RX_DMA_STEAM,DISABLE);
				
		while (DMA_GetCmdStatus(UART4_RX_DMA_STEAM) != DISABLE){}	//等待传输结束		
		
	  uint32_t lenth = UART4_TXRX_DMA_MAX - DMA_GetCurrDataCounter(UART4_RX_DMA_STEAM);
			
		DMA_SetCurrDataCounter(UART4_RX_DMA_STEAM,UART4_TXRX_DMA_MAX);
	  DMA_ClearFlag(UART4_RX_DMA_STEAM,DMA_FLAG_TCIF2);
					
	  DMA_Cmd(UART4_RX_DMA_STEAM,ENABLE);
			
		struct t_uart4_seg *plist = _cli_uart4_rx.list + _cli_uart4_rx.pos_push;
		plist->len = lenth;
	  plist->head = 0;
	  plist->pushstate = 1;
		_cli_uart4_rx.pos_push= (_cli_uart4_rx.pos_push+1)%UART4_RX_MAX;
			
  	usart4_rx_init();
	}	
}

/*
    无线模块 串口5 TX = PC12   RX = PD2
*/
void usart5_init(uint32_t baud){
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
    
	/* 打开 GPIO 时钟 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC |RCC_AHB1Periph_GPIOD, ENABLE);

	/* 打开 UART 时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);

	/* 将 PC12 映射为 UART5_TX */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);

	/* 将 PD2 映射为 UART5_RX */
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);

	/* 配置 UART Tx 为复用功能 */
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	/* 输出类型为推挽 */
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	/* 内部上拉电阻使能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;	/* 复用模式 */

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	/* 配置 UART Rx 为复用功能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	/* 第2步： 配置串口硬件参数 */
	USART_InitStructure.USART_BaudRate = baud;	/* 波特率 */
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(UART5, &USART_InitStructure);

    uart5_recv_queue = xQueueCreate(64, sizeof(uint8_t));
    
	USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);	/* 使能接收中断 */
	/*
		USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
		注意: 不要在此处打开发送中断
		发送中断使能在SendUart()函数打开
	*/
	USART_Cmd(UART5, ENABLE);		/* 使能串口 */

	/* CPU的小缺陷：串口配置好，如果直接Send，则第1个字节发送不出去
		如下语句解决第1个字节无法正确发送出去的问题 */
	USART_ClearFlag(UART5, USART_FLAG_TC);     /* 清发送完成标志，Transmission Complete flag */
	
}

void usart5_send(const uint8_t *buf, uint32_t len){
    for (uint32_t i = 0; i < len; i++) {
        USART_SendData(UART5, *(buf + i));
        while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET) {
            os_msleep(1);
        }
    }
}

int32_t usart5_receive(uint8_t *chr){
    BaseType_t xResult = xQueueReceive(uart5_recv_queue, chr, portTICK_PERIOD_MS);
    if (xResult != pdPASS){
    return 0;
    }
    return 1;
}


void UART5_IRQHandler(void) {
	 uint8_t res;
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
  
	if(USART_GetITStatus(UART5,USART_IT_RXNE) != RESET)  //接收到数据
	{
		res = USART_ReceiveData(UART5) & 0x00FF;	//读取接收到的数据
        xQueueSendFromISR(uart5_recv_queue, &res, &xHigherPriorityTaskWoken);
        USART_ClearITPendingBit(UART5,USART_IT_RXNE); 
	}
}
/*
    预留 串口6 TX = PC6   RX = PC7
*/
#define USART6_TX_DMA_STEAM DMA2_Stream7
#define USART6_RX_DMA_STEAM DMA2_Stream1
#define USART6_TXRX_DMA_MAX 64

struct t_cli_usart6_rx
{
	uint8_t buffer[USART6_TXRX_DMA_MAX];
	uint32_t len;
	uint32_t posread ;
};
struct t_cli_usart6_rx _cli_usart6_rx;
uint8_t _cli_usart6_tx[USART6_TXRX_DMA_MAX];

void usart6_dma_tx_init(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);   
	
   DMA_DeInit(USART6_TX_DMA_STEAM);  
	 while (DMA_GetCmdStatus(USART6_TX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure.DMA_Channel = DMA_Channel_5; 
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART6->DR);  
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(_cli_usart6_tx); 
   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;  
   DMA_InitStructure.DMA_BufferSize = USART6_TXRX_DMA_MAX;  
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;   
	 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//单次传输 
	 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设单次突发
		 
   DMA_Init(USART6_TX_DMA_STEAM,&DMA_InitStructure);  
		 
	 DMA_ClearFlag(USART6_TX_DMA_STEAM,DMA_IT_TCIF7);
		 
	 DMA_Cmd(USART6_TX_DMA_STEAM, ENABLE);
   USART_DMACmd(USART6,USART_DMAReq_Tx,ENABLE);  
}
void usart6_dma_rx_init(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);   
 
  DMA_DeInit(USART6_RX_DMA_STEAM);  
	
	while (DMA_GetCmdStatus(USART6_RX_DMA_STEAM) != DISABLE){}
		
   DMA_InitStructure.DMA_Channel = DMA_Channel_5; 
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART6->DR);  
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(_cli_usart6_rx.buffer); 
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;  
   DMA_InitStructure.DMA_BufferSize = USART6_TXRX_DMA_MAX;  
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;   
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;   
   DMA_Init(USART6_RX_DMA_STEAM,&DMA_InitStructure);  
		 
	 DMA_Cmd(USART6_RX_DMA_STEAM,ENABLE); 
	 USART_DMACmd(USART6,USART_DMAReq_Rx,ENABLE);  
}
void usart6_init(uint32_t baud){
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	/* 打开 GPIO 时钟 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

	/* 打开 UART 时钟 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);

	/* 将 PG14 映射为 USART6_TX */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);

	/* 将 PC7 映射为 USART6_RX */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);


	/* 配置 PC6/USART6_TX 为复用功能 */
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	/* 输出类型为推挽 */
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	/* 内部上拉电阻使能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;	/* 复用模式 */

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	/* 配置 PC7/USART6_RX 为复用功能 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	/* 第2步： 配置串口硬件参数 */
	USART_InitStructure.USART_BaudRate = baud;	/* 波特率 */
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART6, &USART_InitStructure);

	USART_ITConfig(USART6, USART_IT_IDLE, ENABLE);	/* 使能接收中断 */

	USART_Cmd(USART6, ENABLE);		/* 使能串口 */

	usart6_dma_tx_init();
	usart6_dma_rx_init();
	
  uint32_t temp = 0;  
	temp = USART6->SR;  
  temp = USART6->DR; 
}

void usart6_send(const uint8_t *buf, uint32_t len){
	while(1){
	  if((DMA_GetFlagStatus(USART6_TX_DMA_STEAM,DMA_IT_TCIF7)!=RESET)){	
	  DMA_ClearFlag(USART6_TX_DMA_STEAM,DMA_IT_TCIF7);
		break;
		}
	}
	DMA_Cmd(USART6_TX_DMA_STEAM, DISABLE);
	while (DMA_GetCmdStatus(USART6_TX_DMA_STEAM) != DISABLE){}
	
  memcpy(_cli_usart6_tx,buf,len);
	DMA_SetCurrDataCounter(USART6_TX_DMA_STEAM,len);
  
	DMA_Cmd(USART6_TX_DMA_STEAM, ENABLE);	
}

int32_t usart6_receive(uint8_t *chr){

	if(_cli_usart6_rx.posread == _cli_usart6_rx.len){
		return 0;
	}
	*chr = _cli_usart6_rx.buffer[_cli_usart6_rx.posread];
	_cli_usart6_rx.posread ++;
	return 1;
}


void USART6_IRQHandler(void) {

	if(USART_GetITStatus(USART6,USART_IT_IDLE) != RESET){  //接收到数据
  	uint32_t temp = 0;  
	  temp = USART6->SR;  
    temp = USART6->DR; //清USART_IT_IDLE标志 
 		
		DMA_Cmd(USART6_RX_DMA_STEAM,DISABLE);
				
		while (DMA_GetCmdStatus(USART6_RX_DMA_STEAM) != DISABLE){}	//等待传输结束		
		
	  _cli_usart6_rx.len = USART6_TXRX_DMA_MAX - DMA_GetCurrDataCounter(USART6_RX_DMA_STEAM);
		_cli_usart6_rx.posread  = 0;
	
		DMA_SetCurrDataCounter(USART6_RX_DMA_STEAM,USART6_TXRX_DMA_MAX);
	  DMA_ClearFlag(USART6_RX_DMA_STEAM,DMA_FLAG_TCIF1);
					
	  DMA_Cmd(USART6_RX_DMA_STEAM,ENABLE);
		
	}	
}
